/*
A tool similar rsh
Client send shell command to mutiple servers and then print the result on stdout
This code is for server
Author: Zhuo Chen (Calvin
*/

#include<stdio.h>
#include<errno.h>
#include<sys/socket.h>
#include<syslog.h>
#include<netdb.h>
#include<unistd.h>


#define BUFLEN 128
#define RESULTBUF 256
#define QLEN 10
#define SERVER_PORT 1501

#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 256
#endif

int initserver(int tpye,struct sockaddr *addr, socklen_t alen,int qlen);
void server(int sockfd);

int 
initserver(int type,struct sockaddr *addr,socklen_t alen,int qlen){
	int fd;
	int err=0;
	int size=50*1024;
	if((fd=socket(addr->sa_family,type,0))<0){
		printf("creat socket error\n");
		return -1;
	}
	setsockopt(fd,SOL_SOCKET,SO_RCVBUF,&size,sizeof(size));
	if(bind(fd,addr,alen)<0){
		printf("bind error\n");
		err=errno;
		goto errout;
	}
	if(type==SOCK_STREAM||type==SOCK_SEQPACKET){
		if(listen(fd,qlen)<0){
			printf("listen error\n"); 
			err=errno;
			goto errout;
		}
	}
	return fd;

errout:
	close(fd);
	errno=err;
	return -1;
}

void
server(int sockfd){
	char buf[RESULTBUF],temp[BUFLEN];
	int clfd,n,len=0;

	for(;;){
		clfd=accept(sockfd,NULL,NULL);
		if(clfd<0){
			syslog(LOG_ERR,"get message:accept error:%s",strerror(errno));
			exit(1);
		}
		/*redirect the stdout to this connected socket, the client can get the result directly*/
		if((fork())==0){
			if(dup2(clfd,STDOUT_FILENO)!=STDOUT_FILENO||dup2(clfd,STDERR_FILENO)!=STDERR_FILENO){
				printf("dup the stdout or stderr to the socket error\n");
				return ;
			}
			n=recv(clfd,buf,sizeof(buf),0);

			if(n<0){
				printf("receive the parament error!\n");
				return ;
			}
			system(buf);
			printf("work finish\n");
			shutdown(clfd,SHUT_WR);
			shutdown(clfd,SHUT_RD);
			close(clfd);
		}

		else{
			close(clfd);
		}
	} 
}

int
main(int argc,char *argv[]){
	struct sockaddr_in server_addr;
	int sockfd;
	server_addr.sin_family=AF_INET;
	server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
	server_addr.sin_port=htons(SERVER_PORT);
	printf("hello\n");
	if((sockfd=initserver(SOCK_STREAM,(struct sockaddr *)&server_addr,sizeof(server_addr),QLEN))>=0){
		server(sockfd);
		exit(0);
	}
	exit(1);
}

